package main

import (
	"fmt"
	"math"
	"sort"
	"strconv"
	"time"
)

// 作业1和作业2相关代码

// 定义【形状】接口，定义接口的求面积方法
type Shape interface {
	Area() float64
	Name() string
}

// 定义【圆形】结构体
type circle struct {
	radius float64
}

// 实现对圆形求面积的结构体方法
func (c circle) Area() float64 {
	return math.Pi * c.radius * c.radius
}

// 实现圆形名字的返回
func (c circle) Name() string {
	return "圆形"
}

// 定义【三角形】结构体
type triangle struct {
	base   float64
	height float64
}

// 实现对三角形求面积的结构体方法
func (t triangle) Area() float64 {
	return 0.5 * t.base * t.height
}

// 实现三角形名字的返回
func (t triangle) Name() string {
	return "三角形"
}

// 定义【长方形】结构体
type rectangle struct {
	length float64
	width  float64
}

// 实现对长方形求面积的结构体方法
func (r rectangle) Area() float64 {
	return r.length * r.width
}

func (r rectangle) Name() string {
	return "长方形"
}

// 打印不同的圆形、三角形、长方形的面积
func printShapeInfo(shapes ...Shape) {
	for _, item := range shapes {
		fmt.Printf("%s的面积：%.2f\n", item.Name(), item.Area())
	}
}

// 保留两位小数
func decimal(num float64) float64 {
	num, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", num), 64)
	return num
}

type Entry struct {
	Key   string
	Value float64
}

// 作业3相关代码
func fibonacci(n int, mf map[int]int) int {
	if n < 3 {
		return 1
	}
	if _, ok := mf[n]; ok {
		return mf[n]
	}
	mf[n] = fibonacci(n-1, mf) + fibonacci(n-2, mf)
	return mf[n]
}

func main() {
	// 作业1： 实现对圆形、三角形、长方形求面积

	// 作业2：利用第1题，构造3个以上图形，至少圆形、三角形、长方形各有一个，
	// 对上题的图形按照面积降序排列
	// 构造圆形2个，三角形2个，长方形2个
	c1 := circle{radius: 11.8}
	c2 := circle{radius: 23.5}
	t1 := triangle{base: 8.6, height: 9.7}
	t2 := triangle{base: 18.2, height: 19}
	r1 := rectangle{length: 6.5, width: 5.1}
	r2 := rectangle{length: 16.2, width: 15}

	printShapeInfo(c1, c2, t1, t2, r1, r2)

	m := make(map[string]float64)

	m["c1的面积"] = decimal(c1.Area())
	m["c2的面积"] = decimal(c2.Area())
	m["t1的面积"] = decimal(t1.Area())
	m["t2的面积"] = decimal(t2.Area())
	m["r1的面积"] = decimal(r1.Area())
	m["r2的面积"] = decimal(r2.Area())

	entries := make([]Entry, len(m))
	i := 0
	for k, v := range m {
		entries[i] = Entry{k, v}
		i++
	}

	// 按面积降序排列
	sort.Slice(entries, func(i, j int) bool {
		return entries[i].Value > entries[j].Value
	})
	fmt.Println(entries)

	fmt.Println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")

	// 作业3：分析斐波那契数列递推公式递归版本的问题，
	// 试着为该函数提供一个Cache，使其计算效率提升
	n := 10
	mf := make(map[int]int)
	fmt.Printf("第 %v 个 fibonacci 数列的值是：%+v\n", n, fibonacci(n, mf))

	fmt.Println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")

	// 作业4: 8年前的今天上午9点30分
	// 要求：
	// 1.毫秒时间戳是多少？
	// 2.格式化输出时间为 2005/09/10 21:35:40 +0800 的形式
	// 3.请问那天是周几？到那天，本年已经过了多少周？
	// 4.距离今天已经过了多少天了？
	year := strconv.Itoa(time.Now().Year() - 8)
	month := strconv.Itoa(int(time.Now().Month()))
	day := strconv.Itoa(time.Now().Day())
	if len(month) == 1 {
		month = "0" + month
	}
	if len(day) == 1 {
		day = "0" + day
	}
	s := year + "/" + month + "/" + day + " 09:30:00 +0800"

	// 加载时区
	loc, err := time.LoadLocation("Asia/Shanghai")
	if err != nil {
		fmt.Println(err)
		return
	}

	t, err := time.ParseInLocation("2006/01/02 15:04:05 -0700", s, loc)
	if err != nil {
		fmt.Println(err)
	}

	fmt.Printf("毫秒时间戳是：%+v\n", t.UnixMilli())
	fmt.Printf("格式化输出时间为 %+v 的形式\n", t.Format("2006/01/02 15:04:05 -0700"))
	fmt.Printf("这一天是：%+v, ", t.Weekday())
	_, t_week := t.ISOWeek()
	fmt.Printf("到这一天，本年已经过了 %+v 周\n", t_week-1)
	fmt.Printf("距离今天已经过了 %+v 天\n", int(time.Since(t).Hours()/24))
}
